package br.com.velp.sudecap.daoimpl;

import br.com.velp.sudecap.dao.DecretoDAO;
import br.com.velp.sudecap.dto.DecretoParametrosConsultaDTO;
import br.com.velp.sudecap.entidade.Decreto;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

/**
 * <sumario>
 * <objetivo> "Rastreabilidade" </objetivo>
 * <autor> EDUARDO SANTOS DE OLIVEIRA </autor>
 * <versao>1.0.0.0</versao>
 * <data_criacao> 17.10.2012 </data_criacao>
 * <data_ultima_alteracao> N/A </data_ultima_alteracao>
 * <requisitos_afetados> RF006.01 - Listar Decretos / RF006.02 - Cadastrar Decretos </requisitos_afetados>
 * <descricao> Interface Responsável Pelas Operações de CRUD Referentes ao Contexto de Decretos </descricao>
 * </sumario>
 */
@Repository("decretoDAO")
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class DecretoDAOImpl implements DecretoDAO {

    public static final Long serialVersionUID = 1L;
    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public int contarDecretos(DecretoParametrosConsultaDTO parametros) {
	Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Decreto.class);
	criteria.setProjection(Projections.rowCount());
	adicionarParametrosConsulta(criteria, parametros);
	return ((Long) criteria.uniqueResult()).intValue();
    }

    @Override
    public List<Decreto> buscarDecretosPaginados(int firstResult, int maxResults,
	    DecretoParametrosConsultaDTO parametros, Order order) {

	Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Decreto.class);
	criteria.setFirstResult(firstResult);
	criteria.setMaxResults(maxResults);
	adicionarParametrosConsulta(criteria, parametros);

	if (order != null) {
	    criteria.addOrder(order);
	} else {
	    criteria.addOrder(Order.asc("numero"));
	}

	return criteria.list();

    }

    @Override
    public Long salvar(Decreto value) {
	Long id = (Long) sessionFactory.getCurrentSession().save(value);
	sessionFactory.getCurrentSession().flush();
	return id;
    }

    @Override
    public void atualizar(Decreto value) {
	sessionFactory.getCurrentSession().update(value);
	sessionFactory.getCurrentSession().flush();
    }

    @Override
    public Decreto obterPorId(Long id) {
	return (Decreto) sessionFactory.getCurrentSession().get(Decreto.class, id);
    }

    @Override
    public void excluir(Decreto value) {
	sessionFactory.getCurrentSession().delete(value);
	sessionFactory.getCurrentSession().flush();
    }

    private void adicionarParametrosConsulta(Criteria criteria, DecretoParametrosConsultaDTO parametros) {
	if (parametros.getIdDecretoFiltro() != null) {
	    criteria.add(Restrictions.ne("id", parametros.getIdDecretoFiltro()));
	}
	if (parametros.getNumero() != null && !parametros.getNumero().isEmpty()) {
	    criteria.add(Restrictions.eq("numero", parametros.getNumero()));
	}
	if (parametros.getEmenta() != null && !parametros.getEmenta().isEmpty()) {
	    criteria.add(Restrictions.ilike("ementa", parametros.getEmenta(), MatchMode.ANYWHERE));
	}
	if (parametros.getTipoDecreto() != null && !parametros.getTipoDecreto().isEmpty()) {
	    criteria.add(Restrictions.eq("tipoDecreto", parametros.getTipoDecreto()));
	}
	if (parametros.getDataInicial() != null) {
	    criteria.add(Restrictions.ge(parametros.getTipoPeriodo(), parametros.getDataInicial()));
	}
	if (parametros.getDataFinal() != null) {
	    criteria.add(Restrictions.le(parametros.getTipoPeriodo(), parametros.getDataFinal()));
	}
    }

    @Override
    public List<Decreto> recuperarDecretos(Long idDecretoFiltro, String numero) {
	Criteria criteria = this.sessionFactory.getCurrentSession().createCriteria(Decreto.class);
	criteria.addOrder(Order.asc("numero"));
	if (idDecretoFiltro != null) {
	    criteria.add(Restrictions.ne("id", idDecretoFiltro));
	}
	if (StringUtils.isNotEmpty(numero)){
	    criteria.add(Restrictions.ilike("numero", numero, MatchMode.START));
	}
	return criteria.list();
    }
    
    @Override
    public boolean existeDecretoJaCadastrado(Decreto decreto){
	
	Criteria criteria = this.sessionFactory.getCurrentSession().createCriteria(Decreto.class);
	criteria.setProjection(Projections.rowCount());
	criteria.add(Restrictions.eq("numero", decreto.getNumero()));
	
	if(decreto.getId() != null){
	    criteria.add(Restrictions.ne("id", decreto.getId()));
	}
	
	return ((Long) criteria.uniqueResult()) > 0;
	
    }
    
    @Override
    public Decreto recuperarDecreto(Long id){
	
	StringBuilder consulta = new StringBuilder();
	
	consulta.append("select decreto.id as id, ");
	consulta.append("decreto.dataCadastro as dataCadastro, ");
	consulta.append("decreto.dataCaducacao as dataCaducacao, ");
	consulta.append("decreto.dataPublicacao as dataPublicacao, ");
	consulta.append("decreto.enderecoDom as enderecoDom, ");
	consulta.append("decreto.numero as numero ");
	consulta.append("from Decreto decreto ");
	consulta.append("where decreto.id = :id ");
	
	Query query = this.sessionFactory.getCurrentSession().createQuery(consulta.toString());
	query.setParameter("id", id);
	query.setResultTransformer(Transformers.aliasToBean(Decreto.class));
	
	return (Decreto) query.uniqueResult();
	
    }
    
}
